#include "fs/inode.h"
#include "assert.h"
#include "error.h"
#include "fs/deffs.h"
#include "fs/vfs.h"
#include "mmu.h"
#include "stdio.h"
#include "string.h"

inode_t*
__alloc_inode(uint32_t type) {
    inode_t* node = kmalloc(sizeof(inode_t));
    if (node != NULL)
        node->inodeType = type;
    return node;
}

void
inode_init(inode_t* node, const inodeOps_t* ops, fs_t* fs) {
    node->refCount = 0;
    node->openCount = 0;
    node->inodeOps = ops;
    node->inodeFS = fs;
    vop_refInc(node);
}

void
inode_kill(inode_t* node) {
    assert(inode_refCount(node) == 0);
    assert(inode_openCount(node) == 0);
    kmfree(node);
}

int
inode_refInc(inode_t* node) {
    return ++node->refCount;
}

int
inode_refDec(inode_t* node) {
    assert(inode_refCount(node) > 0);
    int refCount;
    --node->refCount;
    refCount = node->refCount;
    if (refCount == 0) {
        int ret = vop_reclaim(node);
        if (ret != 0 && ret != E_BUSY)
            printf("vfs: warning: vop_reclaim: %d.\n", ret);
    }
    return refCount;
}

int
inode_openInc(inode_t* node) {
    return ++node->openCount;
}

int
inode_openDec(inode_t* node) {
    assert(inode_openCount(node) > 0);
    --node->openCount;
    int openCount = node->openCount;
    if (openCount == 0) {
        int ret = vop_close(node);
        if (ret != 0)
            printf("vfs: warning: vop_close: %d.\n", ret);
    }
    return openCount;
}

void
inode_check(inode_t* node, const char* opstr) {
    assert(node != NULL && node->inodeOps != NULL);
    assert(node->inodeOps->vop_magic == VOP_MAGIC);
    int refCount = inode_refCount(node);
    int openCount = inode_openCount(node);
    assert(refCount >= openCount && openCount >= 0);
    assert(refCount < MAX_INODE_COUNT && openCount < MAX_INODE_COUNT);
}